package com.stars.easyms.rest;

import com.alibaba.fastjson.JSON;
import com.stars.easyms.base.bean.EasyMsRequestEntity;
import com.stars.easyms.base.trace.EasyMsTraceSynchronizationManager;
import com.stars.easyms.base.util.MessageFormatUtil;
import com.stars.easyms.rest.bean.RestInfo;
import com.stars.easyms.rest.bean.RestLockInfo;
import com.stars.easyms.rest.bean.EasyMsRestContext;
import com.stars.easyms.rest.exception.BusinessRestException;
import com.stars.easyms.rest.exception.RestRuntimeException;
import com.stars.easyms.rest.handler.EasyMsRestSynchronizationManager;
import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Rest服务的接口类，为每一个接口建立一个独立的事务
 *
 * @author guoguifang
 * @date 2018-10-12 11:24
 * @since 1.0.0
 */
public interface RestService<I, O> {

    /**
     * 接口服务实现方法
     *
     * @param input 输入类
     * @return 输出类
     * @throws BusinessRestException 可抛出BusinessRestException异常
     */
    @Nullable
    O execute(@Nullable I input) throws BusinessRestException;

    /**
     * 为每一个接口提供加锁方案，根据input返回锁名称，如果锁名称不为null，则默认开启加锁，当下次有相同锁名称的时候会直接抛出加锁异常
     *
     * @param restInfo 当前rest接口信息
     * @param input    实现了Input接口的输入类
     * @return 锁信息
     */
    @Nullable
    default RestLockInfo getRestLockInfo(@NonNull RestInfo restInfo, @Nullable I input) {
        return null;
    }

    /**
     * 获取HttpServletRequest对象
     *
     * @return HttpServletRequest对象
     */
    @NonNull
    default HttpServletRequest getRequest() {
        return getEasyMsRestContext().getHttpServletRequest();
    }

    /**
     * 获取HttpServletResponse对象
     *
     * @return HttpServletResponse对象
     */
    @NonNull
    default HttpServletResponse getResponse() {
        return getEasyMsRestContext().getHttpServletResponse();
    }

    /**
     * 获取rest请求信息
     *
     * @return rest请求信息
     */
    @NonNull
    default EasyMsRestContext getEasyMsRestContext() {
        return EasyMsRestSynchronizationManager.getEasyMsRestContext();
    }

    /**
     * 获取请求信息
     *
     * @return 请求信息
     */
    @NonNull
    default EasyMsRequestEntity getRequestEntity() {
        return getEasyMsRestContext().getEasyMsRequestEntity();
    }

    /**
     * 获取rest接口信息
     *
     * @return rest接口信息
     */
    @NonNull
    default RestInfo getRestInfo() {
        return getEasyMsRestContext().getRestInfo();
    }

    /**
     * 获取rest接口可以支持aop的实例对象
     *
     * @return rest接口可以支持aop的实例对象
     */
    @NonNull
    @SuppressWarnings("unchecked")
    default <T> T getThis() {
        return (T) getRestInfo().getRestServiceInstance();
    }

    /**
     * 从请求头中获取用户信息
     *
     * @return 当前用户信息
     */
    @NonNull
    @SuppressWarnings("unchecked")
    default <T> T getUserInfo() {
        String userInfoStr = EasyMsTraceSynchronizationManager.getDecodedCurrentUserInfo();
        if (StringUtils.isNotBlank(userInfoStr)) {
            return (T) JSON.parseObject(userInfoStr, getRestInfo().getUserInfoClass());
        }
        throw new RestRuntimeException("Get User Info fail!");
    }

    /**
     * 使用占位符的字符串进行格式化
     *
     * @param str  待格式化的字符串
     * @param args 占位符参数
     * @return 格式化后的字符串
     */
    default String messageFormat(String str, Object... args) {
        return MessageFormatUtil.format(str, args);
    }

    /**
     * 返回一个空返回
     *
     * @return
     */
    default Void emptyReturn() {
        return null;
    }

}